package learnjdk.parallel;


import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 *
 * 100000 * 100000 经测试串行执行下stream 比 普通迭代慢，大概是5倍左右
 *
 * 100000000 * 1  基本相同
 *
 *
 * 加了wrapper 后差了4.5倍
 *
 *
 * Created by alex on 2017/7/15.
 */
public class Main {

    public static void main(String[] args) {
        List<Integer> list = buildTestList(10000, 14);
        System.out.println("size:"+ list.size());
        long t0 = System.currentTimeMillis();
        looper(Main::serialTest, list, 50);
        System.out.println("cost:" + (System.currentTimeMillis() - t0));
    }

    public static void main2(String[] args) {
        List<Wrapper> list = buildTestWrapperList(1000, 14);
        long t0 = System.currentTimeMillis();
        looper(Main::serialWrapperTest, list, 300);
        System.out.println("cost:" + (System.currentTimeMillis() - t0));
    }

    public static List<Integer> buildTestList(long n, int c) {
        List<Integer> list = new ArrayList<>((int) (n * Math.pow(2, c)));
        for (int i = 1; i <= n; i++) {
            list.add(i);
        }
        for (int i = 0; i < c; i++) {
            list.addAll(list);
        }
        return list;
    }

    private static List<Wrapper> buildTestWrapperList(long n, int c) {
        List<Wrapper> list = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            list.add(new Wrapper(i));
        }
        for (int i = 1; i <= c; i++) {
            list.addAll(list);
        }
        return list;
    }

    public static <T> void looper(Consumer<T> fun, T arg, int loopNum) {
        for (int i = 0; i < loopNum; i++) {
            fun.accept(arg);
        }
    }

    // stream 串行
    private static void serialTest2(List<Integer> list) {
        int sum = list.stream().mapToInt(a -> a.intValue()).reduce(0, Integer::sum);

//        System.out.println("sum:" + sum);
    }

    private static void serialWrapperTest2(List<Wrapper> list) {
        list.stream().reduce(new Wrapper(0), (a, b) -> {
            a.i += b.i;
            return a;
        });
    }

    // stream 并行
    private static void parallelTest(List<Integer> list) {
        list.parallelStream().mapToInt(a -> a.intValue()).reduce(0, Integer::sum);
    }

    private static void parallelWrapperTest(List<Wrapper> list) {
        list.parallelStream().reduce(new Wrapper(0), (a, b) -> {
            a.i += b.i;
            return a;
        });
    }

    // 普通迭代
    private static void serialTest(List<Integer> list) {
        int sum = 0;
        for (int i : list) {
            sum += i;
        }
//        System.out.println("sum:" + sum);
    }

    private static void serialWrapperTest(List<Wrapper> list) {
        int sum = 0;
        for (Wrapper i : list) {
            sum += i.i;
        }
//        System.out.println("sum:" + sum);
    }

    private static class Wrapper {
        private int i;

        public Wrapper(int i) {
            this.i = i;
        }
    }

}
